package com.platform.comm.ftp;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.platform.comm.ftp.exception.FtpException;
import lombok.extern.slf4j.Slf4j;

import java.io.*;

@Slf4j
public class DgSFTPClientImpl implements DgFTPClient {

    private String hostname;

    private int port;

    private String username;

    private String password;

    public DgSFTPClientImpl(String hostname, int port, String username, String password) {
        this.hostname = hostname;
        this.port = port;
        this.username = username;
        this.password = password;
    }

    public boolean tryConnect() {
        boolean result = false;
        JSch jSch = new JSch();
        Session session = null;
        ChannelSftp sftp = null;
        try {
            session = jSch.getSession(this.username,this.hostname, this.port);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            session.setTimeout(2000);
            session.connect();
            sftp = (ChannelSftp)session.openChannel("sftp");
            sftp.connect();
            result = true;
        } catch (Exception e) {
            log.error("sftp create channel is error:{}",e);
        } finally {
            if(sftp != null) {
                sftp.disconnect();
            }
            if(session != null) {
                session.disconnect();
            }
        }
        return result;
    }

    /**
     *  下载文件
     * @param sourceDir
     * @param sourceFile
     * @param descFile
     * @return
     */
    @Override
    public File download(String sourceDir, String sourceFile, String descFile) {
        File desc = null;
        FileOutputStream fos = null;
        String source = sourceDir + File.separator + sourceFile;
        ChannelSftp channelSftp = createChannel();
        if(channelSftp == null) {
            throw new FtpException(FtpException.ErrorCode.LOGIN_ERROR);
        }
        try {
            if(!checkFileExist(channelSftp,source)) {
                throw new FtpException(FtpException.ErrorCode.FILE_NOT_FOUND);
            }
            desc = new File(descFile);
            if(desc.exists()){
                desc.delete();
            } if(!desc.getParentFile().exists()) {
                desc.getParentFile().mkdirs();
            }
            fos = new FileOutputStream(descFile);
            channelSftp.get(source,fos);
        } catch (Exception e) {
            desc = null;
            log.error("sftp download file is error:{}",e);
            throw new FtpException(FtpException.ErrorCode.DOWNLOAD_FAILED);
        } finally {
            disconnect(channelSftp);
            if(fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    log.error("sftp close stream is error:{}",e);
                }
            }
        }
        return desc;
    }

    /**
     *  上传文件
     * @param sourceFile
     * @param descDir
     * @param descFile
     */
    public void upload(String sourceFile, String descDir, String descFile) {
        FileInputStream fis = null;
        String desc = descDir + File.separator + descFile;
        ChannelSftp channelSftp = null;
        try {
            channelSftp = createChannel();
            if(channelSftp == null) {
                throw new FtpException(FtpException.ErrorCode.LOGIN_ERROR);
            }
            // 切换目录
            if(checkFileExist(channelSftp,descDir)) {
                fis = new FileInputStream(sourceFile);
                channelSftp.put(fis,desc);
            } else {
                throw new FtpException(FtpException.ErrorCode.FILE_NOT_FOUND);
            }
        } catch (IOException | SftpException e) {
            log.error("sftp upload file is error:{}",e);
            throw new FtpException(FtpException.ErrorCode.FILE_NOT_FOUND);
        } finally {
            try {
                disconnect(channelSftp);
                if(fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                log.error("sftp upload file close stream is error:{}",e);
            }
        }
    }

    public void delete(String descDir, String descFile) {
        ChannelSftp channelSftp = null;
        String desc = descDir + File.separator + descFile;
        try {
            channelSftp = createChannel();
            if(channelSftp == null) {
                throw new FtpException(FtpException.ErrorCode.LOGIN_ERROR);
            }
            // 切换目录
            if(checkFileExist(channelSftp,desc)) {
                channelSftp.rm(desc);
            } else {
                throw new FtpException(FtpException.ErrorCode.FILE_NOT_FOUND);
            }
        } catch (SftpException e) {
            log.error("ftp upload file is error:{}",e);
            throw new FtpException(FtpException.ErrorCode.DELETE_FAILED);
        } finally {
            disconnect(channelSftp);
        }
    }

    /**
     *  关闭连接
     * @param channelSftp
     */
    private void disconnect(ChannelSftp channelSftp) {
        try {
            if( channelSftp == null){
                return;
            }
            if(channelSftp.isConnected()){
                channelSftp.disconnect();
            }
            if(channelSftp.getSession() != null){
                channelSftp.getSession().disconnect();
            }
        } catch(Exception e) {
            log.error("sftp disconnect is error:{}",e);
        }
    }

    /**
     * 判断文件是否存在
     * @param channelSftp
     * @param source
     * @return
     */
    private boolean checkFileExist(ChannelSftp channelSftp, String source) {
        boolean result = false;
        try {
            return channelSftp.ls(source).size() != 0;
        } catch (SftpException e) {
            log.error("sftp check file exist is error:{}",e);
        }
        return result;
    }

    /**
     *  创建连接通道
     * @return
     */
    private ChannelSftp createChannel()  {
        JSch jSch = new JSch();
        Session session = null;
        ChannelSftp sftp = null;
        try {
            session = jSch.getSession(this.username,this.hostname, this.port);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();
            sftp = (ChannelSftp)session.openChannel("sftp");
            sftp.connect();
        } catch (Exception e) {
            log.error("sftp create channel is error:{}",e);
            if(sftp != null) {
                sftp.disconnect();
            }
            if(session != null) {
                session.disconnect();
            }
            throw new FtpException(FtpException.ErrorCode.LOGIN_ERROR);
        }
        return sftp;
    }


    /*public static void main(String[] args) {
        DgSftpClient client = new DgSftpClient("192.168.0.117",22, "kingdee","ftp12345");
        System.out.println(client.tryConnect());
        //client.upload("/Users/master/data/code/learn/test-demo/src/main/resources/dir/haha.xlsx","/home/kingdee/1/2","11.xlsx");
        //client.download("/home/kingdee/1/2","11.xlsx","/Users/master/data/code/learn/test-demo/src/main/resources/dir/11haha.xlsx");
        client.delete("/home/kingdee/1/2","11.xlsx");
    }*/
}
